From: Keir Fraser Date: Wed, 29 Oct 2008 10:14:13 +0000 (+0000) Subject: cpufreq: domain structure update from array to linked list X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14054^2~17 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=9e9a85e47bf684060eba3d1cc4e84bf5d636ad71;p=xen.git cpufreq: domain structure update from array to linked list Current cpufreq domain is an array cpufreq_dom_map[NR_CPUS]. However, domain number may be sparse or bigger than NR_CPUS. Signed-off-by: Jinsong Liu --- diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c index 7907547d69..eb88e1744b 100644 --- a/xen/drivers/cpufreq/cpufreq.c +++ b/xen/drivers/cpufreq/cpufreq.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +45,12 @@ #include #include -/* TODO: change to link list later as domain number may be sparse */ -static cpumask_t cpufreq_dom_map[NR_CPUS]; +struct cpufreq_dom { + unsigned int dom; + cpumask_t map; + struct list_head node; +}; +static LIST_HEAD(cpufreq_dom_list_head); int cpufreq_limit_change(unsigned int cpu) { @@ -72,48 +77,71 @@ int cpufreq_add_cpu(unsigned int cpu) { int ret = 0; unsigned int firstcpu; - unsigned int dom; + unsigned int dom, domexist = 0; unsigned int j; + struct list_head *pos; + struct cpufreq_dom *cpufreq_dom; struct cpufreq_policy new_policy; struct cpufreq_policy *policy; struct processor_performance *perf = &processor_pminfo[cpu]->perf; /* to protect the case when Px was not controlled by xen */ - if (!processor_pminfo[cpu] || !(perf->init & XEN_PX_INIT)) - return 0; - - if (!cpu_online(cpu) || cpufreq_cpu_policy[cpu]) + if (!processor_pminfo[cpu] || + !(perf->init & XEN_PX_INIT) || + !cpu_online(cpu)) return -EINVAL; + if (cpufreq_cpu_policy[cpu]) + return 0; + ret = cpufreq_statistic_init(cpu); if (ret) return ret; dom = perf->domain_info.domain; - if (cpus_weight(cpufreq_dom_map[dom])) { + + list_for_each(pos, &cpufreq_dom_list_head) { + cpufreq_dom = list_entry(pos, struct cpufreq_dom, node); + if (dom == cpufreq_dom->dom) { + domexist = 1; + break; + } + } + + if (domexist) { /* share policy with the first cpu since on same boat */ - firstcpu = first_cpu(cpufreq_dom_map[dom]); + firstcpu = first_cpu(cpufreq_dom->map); policy = cpufreq_cpu_policy[firstcpu]; cpufreq_cpu_policy[cpu] = policy; - cpu_set(cpu, cpufreq_dom_map[dom]); + cpu_set(cpu, cpufreq_dom->map); cpu_set(cpu, policy->cpus); printk(KERN_EMERG"adding CPU %u\n", cpu); } else { + cpufreq_dom = xmalloc(struct cpufreq_dom); + if (!cpufreq_dom) { + cpufreq_statistic_exit(cpu); + return -ENOMEM; + } + memset(cpufreq_dom, 0, sizeof(struct cpufreq_dom)); + cpufreq_dom->dom = dom; + cpu_set(cpu, cpufreq_dom->map); + list_add(&cpufreq_dom->node, &cpufreq_dom_list_head); + /* for the first cpu, setup policy and do init work */ policy = xmalloc(struct cpufreq_policy); if (!policy) { + list_del(&cpufreq_dom->node); + xfree(cpufreq_dom); cpufreq_statistic_exit(cpu); return -ENOMEM; } memset(policy, 0, sizeof(struct cpufreq_policy)); - - cpufreq_cpu_policy[cpu] = policy; - cpu_set(cpu, cpufreq_dom_map[dom]); + policy->cpu = cpu; cpu_set(cpu, policy->cpus); + cpufreq_cpu_policy[cpu] = policy; - policy->cpu = cpu; ret = cpufreq_driver->init(policy); if (ret) goto err1; @@ -124,7 +152,7 @@ int cpufreq_add_cpu(unsigned int cpu) * After get full cpumap of the coordination domain, * we can safely start gov here. */ - if (cpus_weight(cpufreq_dom_map[dom]) == + if (cpus_weight(cpufreq_dom->map) == perf->domain_info.num_processors) { memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); policy->governor = NULL; @@ -138,51 +166,68 @@ int cpufreq_add_cpu(unsigned int cpu) err2: cpufreq_driver->exit(policy); err1: - for_each_cpu_mask(j, cpufreq_dom_map[dom]) { + for_each_cpu_mask(j, cpufreq_dom->map) { cpufreq_cpu_policy[j] = NULL; cpufreq_statistic_exit(j); } - cpus_clear(cpufreq_dom_map[dom]); + list_del(&cpufreq_dom->node); + xfree(cpufreq_dom); xfree(policy); return ret; } int cpufreq_del_cpu(unsigned int cpu) { - unsigned int dom; + unsigned int dom, domexist = 0; + struct list_head *pos; + struct cpufreq_dom *cpufreq_dom; struct cpufreq_policy *policy; struct processor_performance *perf = &processor_pminfo[cpu]->perf; /* to protect the case when Px was not controlled by xen */ - if (!processor_pminfo[cpu] || !(perf->init & XEN_PX_INIT)) - return 0; - - if (!cpu_online(cpu) || !cpufreq_cpu_policy[cpu]) + if (!processor_pminfo[cpu] || + !(perf->init & XEN_PX_INIT) || + !cpu_online(cpu)) return -EINVAL; + if (!cpufreq_cpu_policy[cpu]) + return 0; + dom = perf->domain_info.domain; policy = cpufreq_cpu_policy[cpu]; - printk(KERN_EMERG"deleting CPU %u\n", cpu); + list_for_each(pos, &cpufreq_dom_list_head) { + cpufreq_dom = list_entry(pos, struct cpufreq_dom, node); + if (dom == cpufreq_dom->dom) { + domexist = 1; + break; + } + } + + if (!domexist) + return -EINVAL; /* for the first cpu of the domain, stop gov */ - if (cpus_weight(cpufreq_dom_map[dom]) == + if (cpus_weight(cpufreq_dom->map) == perf->domain_info.num_processors) __cpufreq_governor(policy, CPUFREQ_GOV_STOP); cpufreq_cpu_policy[cpu] = NULL; cpu_clear(cpu, policy->cpus); - cpu_clear(cpu, cpufreq_dom_map[dom]); + cpu_clear(cpu, cpufreq_dom->map); cpufreq_statistic_exit(cpu); /* for the last cpu of the domain, clean room */ /* It's safe here to free freq_table, drv_data and policy */ - if (!cpus_weight(cpufreq_dom_map[dom])) { + if (!cpus_weight(cpufreq_dom->map)) { cpufreq_driver->exit(policy); + list_del(&cpufreq_dom->node); + xfree(cpufreq_dom); xfree(policy); } + printk(KERN_EMERG"deleting CPU %u\n", cpu); return 0; }